package net.citigo.tool.s3backup;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import com.amazonaws.auth.PropertiesCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.PutObjectRequest;

public class BackupTool extends TimerTask {	
	
	private File credPropFile;
	private Properties config;
	private Logger logger;

	public BackupTool(File credPropFile, Properties config) {
		this.credPropFile = credPropFile;
		this.config = config;
		try {
		    // Create a file handler that write log record to a file called my.log
		    FileHandler handler = new FileHandler("s3backup.log");

		    // Add to the desired logger
		    Logger logger = Logger.getLogger("net.citigo.tool.s3backup");
		    logger.addHandler(handler);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void run() {
		// do backup
		try {
			String targetPath = config.getProperty(App.WORKING_FOLDER) + "/" + config.getProperty(App.FILE_NAME);
			zipFolder(config.getProperty(App.BACKUP_FOLDER), targetPath);
			
			File targetFile = new File(targetPath);
			upload(targetFile);			
			logger.log(Level.INFO, "Upload successfully!");
			
			targetFile.delete();
		} catch (IOException e) {
			logger.log(Level.SEVERE, e.getMessage());
		} catch (IllegalArgumentException e) {
			logger.log(Level.SEVERE, e.getMessage());
		}
	}
	
	public void upload(File file) throws IllegalArgumentException, IOException {
		AmazonS3 s3 = new AmazonS3Client(new PropertiesCredentials(credPropFile));
		s3.putObject(new PutObjectRequest(config.getProperty(App.BUCKET), config.getProperty(App.OBJECT_NAME), file));
	}

	public static void zipFolder(String srcFolder, String destZipFile) throws IOException {
		ZipOutputStream zip = null;
		FileOutputStream fileWriter = null;

		fileWriter = new FileOutputStream(destZipFile);
		zip = new ZipOutputStream(fileWriter);

		addFolderToZip("", srcFolder, zip);
		zip.flush();
		zip.close();
	}

	private static void addFileToZip(String path, String srcFile, ZipOutputStream zip) throws IOException {

		File folder = new File(srcFile);
		if (folder.isDirectory()) {
			addFolderToZip(path, srcFile, zip);
		} else {
			byte[] buf = new byte[1024];
			int len;
			FileInputStream in = new FileInputStream(srcFile);
			zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
			while ((len = in.read(buf)) > 0) {
				zip.write(buf, 0, len);
			}
		}
	}

	private static void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) throws IOException {
		File folder = new File(srcFolder);
		
		if (folder.isDirectory() && folder.list().length == 0) {
			zip.putNextEntry(new ZipEntry(path + "/" + folder.getName() + "/"));
			zip.closeEntry();
		}
		else {
			for (String fileName : folder.list()) {
				if (path.equals("")) {
					addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip);
				} else {
					addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip);
				}
			}	
		}
	}

}
